#include "protocol.h"
#include "connection.h"
#include "server.h"
#include "connectionclosedexception.h"
#include "parser.h"
#include "dbinmemory.h"
#include "dbsave.h"
#include "dbinterface.h"
#include <iostream>
#include <cstdlib>
#include <memory>

using namespace std;

//vector<unsigned char> read(const shared_ptr<Connection>& conn, Server& server);
void write(const shared_ptr<Connection>& conn, vector<unsigned char> req);

int main(int argc, char* argv[]){
	dbinmemory db;
	dbinterface* dbpoint = &db;

	Parser parser=Parser(dbpoint);
	if (argc != 2) {
		cerr << "Usage: myserver port-number" << endl;
		exit(1);
	}
	int port = -1;
	try {
		port = stoi(argv[1]);
	} catch (exception& e) {
		cerr << "Wrong port number. " << e.what() << endl;
		exit(1);
	}
	Server server(port);
	if (!server.isReady()) {
		cerr << "Server initialization error." << endl;
		exit(1);
	}
	
	while (true) {
		
		cout << "Waiting for activity" << endl;
		auto conn = server.waitForActivity();
		try {
			cout << "Activity detected, handling..." << endl;
			vector<unsigned char> req;
			if (conn != nullptr) {
				//req = read(conn, server);
				req = parser.handle_input(conn);
				write(conn, req);
			} else {
				conn = make_shared<Connection>();
				server.registerConnection(conn);
				cout << "New client connects" << endl;
			}
		} catch (ConnectionClosedException&) {
			server.deregisterConnection(conn);
			cout << "Client closed connection" << endl;
		} catch (invalid_argument& ia) {
			server.deregisterConnection(conn); //Close connection to client if client does not follow protocol
			cerr << ia.what() << endl;
		} catch (exception& e) {
			cerr << "Unhandled exception: " << e.what() << endl;
			cerr << "Shutting down" << endl;
			exit(1);
		}
	}
}

void write(const shared_ptr<Connection>& conn, vector<unsigned char> req) {
	for(auto it= req.begin(); it < req.end(); ++it){
		conn->write(*it);
	}
}
